﻿/*++
 * Copyright (c) DemeterSoft Corporation
 *
 * File Name:
 *     SlViewContainer.cs
 *     
 * Abstract:
 *     SlViewContainer视图容器
 *     SwitchDirection视图切换方向
 *
 * Revision History:
 *     08/24/2011    yliu
 *         创建文件
 * --*/

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Windows.Controls.Primitives;

namespace SmartSpace.Silverlight
{
    /// <summary>
    /// 视图切换的方向
    /// </summary>
    public enum SwitchDirection
    {
        /// <summary>
        /// 没有切换动作
        /// </summary>
        None,

        /// <summary>
        /// 向前
        /// </summary>
        Forward,

        /// <summary>
        /// 向后
        /// </summary>
        Backward,
    }

    /// <summary>
    /// 视图容器
    /// </summary>
    public class SlViewContainer : Grid
    {
        #region fields

        /// <summary>
        /// 视图容器状态观察者
        /// </summary>
        private List<ISlViewContainerObserver> m_observers = new List<ISlViewContainerObserver>();

        /// <summary>
        /// 视图列表
        /// </summary>
        private List<SlView> m_views = new List<SlView>();

        /// <summary>
        /// 切换效果
        /// </summary>
        private SwitchEffect m_switchEffect;

        /// <summary>
        /// 回退操作时，要回退的目的地视图
        /// </summary>
        private SlView m_backDestinationView;

        private Size m_containerSize;

        #endregion

        #region properties

        /// <summary>
        /// 获得视图列表
        /// </summary>
        public List<SlView> Views
        {
            get
            {
                return m_views;
            }
        }

        /// <summary>
        /// 获得当前显示的视图
        /// </summary>
        public SlView CurrentView
        {
            get
            {
                if (m_views.Count > 0)
                {
                    return m_views[m_views.Count - 1];
                }
                return null;
            }
        }

        /// <summary>
        /// 设置视图切换效果
        /// </summary>
        public SwitchEffect SwitchEffect
        {
            set
            {
                if (m_switchEffect != value)
                {
                    m_switchEffect.SwitchCompleted -= new SwitchCompletedEventHandler(m_switchEffect_SwitchCompleted);
                    m_switchEffect = value;
                    m_switchEffect.SwitchCompleted += new SwitchCompletedEventHandler(m_switchEffect_SwitchCompleted);
                }
            }
        }

        #endregion

        public SlViewContainer()
        {
            m_switchEffect = new NormalSwitchEffect();
            m_switchEffect.SwitchCompleted += new SwitchCompletedEventHandler(m_switchEffect_SwitchCompleted);

            m_containerSize = new Size();
            this.SizeChanged += new SizeChangedEventHandler(OnSilverlightViewContainerSizeChanged);
        }

        void m_switchEffect_SwitchCompleted(SlView outView, SlView inView, SwitchDirection direction)
        {
            OnSwitchViewCompleted(outView, inView);
        }

        /// <summary>
        /// 附件容器的观察者
        /// </summary>
        /// <param name="observer"></param>
        public void Attach(ISlViewContainerObserver observer)
        {
            m_observers.Add(observer);
            observer.Update(this);
        }

        #region api methods

        /// <summary>
        /// 切换视图
        /// </summary>
        /// <param name="view"></param>
        public void SwitchView(SlView view)
        {
            if (m_switchEffect.IsSwitching)
            {
                // 正在切换中
                return;
            }

            foreach (SlView existView in m_views)
            {
                if (view == existView)
                {
                    // 视图已经存在于视图列表中
                    return;
                }
            }

            if (CurrentView != null && !CurrentView.ConfirmExit())
            {
                // 视图存在，并且当前视图不允许取消
                return;
            }

            PrepareSwitch(CurrentView, view, SwitchDirection.Forward);

            m_views.Clear();
            m_views.Add(view);
            view.ViewContainer = this;

            m_switchEffect.Begin();
        }

        public void SwitchView(SlView view, SwitchDirection direction)
        {
            if (m_switchEffect.IsSwitching)
            {
                // 正在切换中
                return;
            }

            foreach (SlView existView in m_views)
            {
                if (view == existView)
                {
                    // 视图已经存在于视图列表中
                    return;
                }
            }

            if (CurrentView != null && !CurrentView.ConfirmExit())
            {
                // 视图存在，并且当前视图不允许取消
                return;
            }

            view.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
            PrepareSwitch(CurrentView, view, direction);

            m_views.Clear();
            m_views.Add(view);
            view.ViewContainer = this;

            m_switchEffect.Begin();
        }

        /// <summary>
        /// 切换子视图
        /// PS:该函数主要被SlView调用
        /// </summary>
        /// <param name="parentView"></param>
        /// <param name="subView"></param>
        internal void SwitchSubView(SlView parentView, SlView subView)
        {
            if (m_switchEffect.IsSwitching)
            {
                // 正在切换中
                return;
            }

            subView.HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
            PrepareSwitch(CurrentView, subView, SwitchDirection.Forward);

            m_views.Add(subView);
            subView.ViewContainer = this;

            m_switchEffect.Begin();
        }

        /// <summary>
        /// 回退视图
        /// </summary>
        public void GoBack()
        {
            if (m_switchEffect.IsSwitching)
            {
                // 正在切换中
                return;
            }

            if (m_views.Count <= 1)
            {
                // 没有可以回退的视图了
                return;
            }

            if (CurrentView != null && !CurrentView.ConfirmExit())
            {
                // 视图存在，并且当前视图不允许取消
                return;
            }

            PrepareSwitch(CurrentView, CurrentView.ParentView, SwitchDirection.Backward);

            m_views.Remove(CurrentView);

            m_switchEffect.Begin();
        }

        /// <summary>
        /// 回退到某视图
        /// </summary>
        /// <param name="view"></param>
        public void GoBack(SlView view)
        {
            if (m_switchEffect.IsSwitching)
            {
                // 正在切换中
                return;
            }

            // 设置回退的目的视图
            m_backDestinationView = view;

            if (CurrentView != m_backDestinationView)
            {   
                // 开始回退
                GoBack();
            }
            else
            {
                // 当前视图已经是要回退的目的视图,不需要回退
                m_backDestinationView = null;
            }
        }

        #endregion

        /// <summary>
        /// 视图切换完毕
        /// </summary>
        /// <param name="outView">隐藏的视图</param>
        /// <param name="inView">显示的视图</param>
        private void OnSwitchViewCompleted(SlView outView, SlView inView)
        {
            // 更新界面上得视图显示
            for (int index = this.Children.Count - 1; index >= 0; index--)
            {
                if (this.Children[index] != inView)
                {
                    this.Children.RemoveAt(index);
                }
            }

            // 通知观察者
            Notify();

            if (outView != null)
            {
                outView.SwitchComplated(false);
            }

            inView.SwitchComplated(true);

            // 如果是回退,判断是否已经回退到指定的位置
            if (m_backDestinationView != null)
            {
                if (inView != m_backDestinationView)
                {
                    // 继续回退
                    GoBack();
                }
                else
                {
                    m_backDestinationView = null;
                    //System.Windows.Browser.HtmlPage.Window.Navigate(new Uri(System.Windows.Browser.HtmlPage.Document.DocumentUri, "#" + inView.GetType().Name));
                }
            }
            else
            {
                //System.Windows.Browser.HtmlPage.Window.Navigate(new Uri(System.Windows.Browser.HtmlPage.Document.DocumentUri, "#" + inView.GetType().Name));
            }

        }

        private void Notify()
        {
            foreach (ISlViewContainerObserver observer in m_observers)
            {
                observer.Update(this);
            }
        }

        /// <summary>
        /// 设置要切换的视图
        /// </summary>
        /// <param name="outView">淡出的视图</param>
        /// <param name="inView">淡入的视图</param>
        /// <param name="direction">淡入淡出的方向</param>
        private void PrepareSwitch(SlView outView, SlView inView, SwitchDirection direction)
        {
            this.Children.Clear();
            if (outView != null)
            {
                this.Children.Add(outView);
            }
            this.Children.Add(inView);

            m_switchEffect.PrepareSwitch(this.RenderSize, outView, inView, direction);
        }

        private void OnSilverlightViewContainerSizeChanged(object sender, SizeChangedEventArgs e)
        {
            m_containerSize.Width = this.ActualWidth;
            m_containerSize.Height = this.ActualHeight;

            // 设置裁剪区域
            RectangleGeometry geometry = new RectangleGeometry();
            geometry.Rect = new Rect(0, 0, m_containerSize.Width, m_containerSize.Height);
            this.Clip = geometry;
        }

        internal void ShowMessage(string message)
        {
            Popup p = new Popup();
            TextBlock tb = new TextBlock();
            tb.Text = message;
            p.Child = tb;
            p.IsOpen = true;
        }
    }
}
